<template>
    <div class="tiled-calendar">
        <div class="calendar-header">
            <span :class="getWeekClass(year)">{{ monthCN[month] }}月</span>
        </div>
        <ul class="calendar-week">
            <li
                v-for="(item, index) in calendarWeek"
                :key="index"
                class="calendar-week-item"
                :class="getWeekClass(year, month + 1)"
            >
                {{ item }}
            </li>
        </ul>
        <ul class="calendar-body">
            <li
                v-for="(item, index) in calendar"
                :key="index"
                class="calendar-day"
                @click="onDay(item)"
            >
                <template v-if="hasCurrentMonth">
                    <span
                        class="calendar-day-item"
                        :class="getCellClass(item, index)"
                        >{{ item.day }}</span
                    >
                    <span class="calendar-day-item">
                        {{ lunarDate(item.day, item) }}</span
                    >
                </template>
                <template v-else>
                    <div
                        class="calendar-day-item"
                        :class="getCellClass(item, index)"
                        v-if="isCurrentMonth(item.date)"
                    >
                        <p style="font-size: 14px; font-weight: 600">
                            {{ item.day }}
                            {{ item.dayCodeInfo }}
                        </p>
                        <p>{{ lunarDate(item.day, item) }}</p>
                    </div>
                </template>
            </li>
        </ul>
    </div>
</template>
  
  <script>
import dayjs from "dayjs";
import { getLunar } from "chinese-lunar-calendar";
import schedulingHttp from "@/https/scheduling.js";
import moment from "moment";

const monthCN = [
    "一",
    "二",
    "三",
    "四",
    "五",
    "六",
    "七",
    "八",
    "九",
    "十",
    "十一",
    "十二",
];

const getNewDate = (date) => {
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = date.getDate();
    return { year, month, day };
};

const getDate = (year, month, day) => new Date(year, month, day);

export default {
    props: {
        year: {
            type: [String, Number],
            default: 2023,
        },
        month: {
            type: [String, Number],
            default: 0,
        },
        // 是否在当月日历中展示上个月和下个月的部分日期，默认不展示。
        hasCurrentMonth: {
            type: Boolean,
            default: false,
        },
        // 休息日
        weekendList: Array,
        // 工作日
        workList: {
            type: Array,
            default: () => [],
        },
        // 既非工作日也非休息日
        workRestOffList: Array,
    },
    data() {
        return {
            calendarWeek: ["一", "二", "三", "四", "五", "六", "日"],
            today: dayjs().format("YYYYMMDD"),
            isCtrl: false,
            isShift: false,
            monthCN,
            selectedList: [],
        };
    },
    computed: {
        calendar() {},
    },
    mounted() {
        this.onKeyEvent();
        this.getHoliday();
    },
    methods: {
        onKeyEvent() {
            window.addEventListener("keydown", (e) => {
                const _e = e || window.event;
                switch (_e.keyCode) {
                    case 16:
                        this.isShift = true;
                        break;
                    case 17:
                        this.isCtrl = true;
                        break;
                }
            });

            window.addEventListener("keyup", (e) => {
                const _e = e || window.event;
                switch (_e.keyCode) {
                    case 16:
                        this.isShift = false;
                        break;
                    case 17:
                        this.isCtrl = false;
                        break;
                }
            });
        },
        // 是否是当前月
        isCurrentMonth(date) {
            const { year: currentYear, month: currentMonth } = getNewDate(
                getDate(this.year, this.month, 1)
            );
            const { year, month } = getNewDate(date);
            return currentYear === year && currentMonth === month;
        },
        onDay(item) {
            // 如果是同一年，当点击的月份小于当前系统日期的月份，则禁止点击。
            if (
                item.year === new Date().getFullYear() &&
                item.month < new Date().getMonth() + 1
            ) {
                return;
            }

            // 如果是同一年又是同一个月，当点击的日期小于当前的日期，则禁止点击
            if (
                item.year === new Date().getFullYear() &&
                item.month === new Date().getMonth() + 1 &&
                item.day < new Date().getDate()
            ) {
                return;
            }

            // 如果点击的年份小月当前年份，则禁止点击。
            if (item.year < new Date().getFullYear()) {
                return;
            }

            // 如果点击的日期不是那个月应有的日期（每个月的日期里边也会包含上个月和下个月的某几天日期，只是这些日期的颜色被置灰了），则禁止点击。
            if (!this.isCurrentMonth(item.date)) {
                return;
            }

            const dateStr = dayjs(item.date).format("YYYYMMDD");
            const { isCtrl, isShift } = this;

            // 按住ctrl
            if (isCtrl && !isShift) {
                this.setSelectCalendar({ dateStr, item, isCtrl });
            } else if (isCtrl && isShift) {
                // 同时按住ctrl和shift
                this.setSelectCalendar({ dateStr, item, isCtrl, isShift });
            } else if (isShift && !isCtrl) {
                // 按住shift
                this.setSelectCalendar({ dateStr, item, isShift });
            } else {
                // 不按ctrl和shift，一次只能选择一个
                this.setSelectCalendar({ dateStr, item });
            }
        },
        getWeekClass(year, month) {
            if (year < new Date().getFullYear()) return "is-disabled";

            if (
                year === new Date().getFullYear() &&
                month < new Date().getMonth() + 1
            )
                return "is-disabled";
        },
        getCellClass(item, idx) {
            const { workList, weekendList, workRestOffList } = this;
            const date = dayjs(item.date).format("YYYYMMDD");
            const today = `${item.year}${
                item.month < 10 ? "0" + item.month : item.month
            }${item.day < 10 ? "0" + item.day : item.day}`;

            // 被选中的日期
            const index = this.selectedList.indexOf(date);

            if (index !== -1) {
                // 如果选中的日期是当年日期的周六周日，且这些日期不是工作日，则在选中时还是要保留它原来的红色字体，如果是工作日，则在选中时就不能再展示成红色字体了。
                if (
                    (idx % 7 === 5 || idx % 7 === 6) &&
                    this.isCurrentMonth(item.date) &&
                    item.year >= new Date().getFullYear() &&
                    !(workList.length && workList.includes(date))
                ) {
                    return "is-selected is-weekend";
                } else if (weekendList.length && weekendList.includes(date)) {
                    // 休息日的选中（非周六周日的休息日）
                    return "is-selected is-weekend";
                } else if (
                    workRestOffList.length &&
                    workRestOffList.includes(date)
                ) {
                    // 异常日期的选中
                    return "is-selected is-workRestOff";
                } else {
                    return "is-selected";
                }
            }

            // 默认显示当前日期
            if (today === this.today) {
                // 如果把当前日期也置为休息日，则也是要将当前日期标红
                if (weekendList.length && weekendList.includes(date)) {
                    return "is-today is-weekend";
                }

                // 异常日期
                if (workRestOffList.length && workRestOffList.includes(date)) {
                    return "is-today is-workRestOff";
                }

                return "is-today";
            }

            // 如果日期不是那个月应有的日期（每个月的日期里边也会包含上个月和下个月的某几天日期，只是这些日期的颜色被置灰了），则禁止点击。
            // if (!this.isCurrentMonth(item.date)) {
            //   return 'is-disabled'
            // }

            // 如果是同一年，当月份小于当前系统日期的月份，则禁止点击。
            if (
                item.year === new Date().getFullYear() &&
                item.month < new Date().getMonth() + 1
            ) {
                // 周六周日被设置成了工作日
                if (
                    (idx % 7 === 5 || idx % 7 === 6) &&
                    workList.length &&
                    workList.includes(date)
                ) {
                    return "is-disabled is-work";
                }

                // 异常日期
                if (workRestOffList.length && workRestOffList.includes(date)) {
                    return "is-disabled is-workRestOff";
                }

                // 周六周日标红
                if (
                    idx % 7 === 5 ||
                    idx % 7 === 6 ||
                    (weekendList.length && weekendList.includes(date))
                ) {
                    return "is-disabled is-weekend";
                }

                return "is-disabled";
            }

            // 如果是同一年又是同一个月，当日期小于当前的日期，则禁止点击
            if (
                item.year === new Date().getFullYear() &&
                item.month === new Date().getMonth() + 1 &&
                item.day < new Date().getDate()
            ) {
                // 周六周日被设置成了工作日
                if (
                    (idx % 7 === 5 || idx % 7 === 6) &&
                    workList.length &&
                    workList.includes(date)
                ) {
                    return "is-disabled is-work";
                }

                // 异常日期
                if (workRestOffList.length && workRestOffList.includes(date)) {
                    return "is-disabled is-workRestOff";
                }

                // 周六周日标红
                if (
                    idx % 7 === 5 ||
                    idx % 7 === 6 ||
                    (weekendList.length && weekendList.includes(date))
                ) {
                    return "is-disabled is-weekend";
                }

                return "is-disabled";
            }

            // 如果年份小月当前年份，则禁止点击。
            if (item.year < new Date().getFullYear()) {
                // 周六周日被设置成了工作日
                if (
                    (idx % 7 === 5 || idx % 7 === 6) &&
                    workList.length &&
                    workList.includes(date)
                ) {
                    return "is-disabled is-work";
                }

                // 异常日期
                if (workRestOffList.length && workRestOffList.includes(date)) {
                    return "is-disabled is-workRestOff";
                }

                // 周六周日标红
                if (
                    idx % 7 === 5 ||
                    idx % 7 === 6 ||
                    (weekendList.length && weekendList.includes(date))
                ) {
                    return "is-disabled is-weekend";
                }

                return "is-disabled";
            }

            // 周六周日标红
            if (
                (idx % 7 === 5 || idx % 7 === 6) &&
                this.isCurrentMonth(item.date) &&
                item.year >= new Date().getFullYear()
            ) {
                // 周六周日被设置成了工作日，则不标红
                if (workList.length && workList.includes(date)) {
                    return "is-work";
                }

                if (workRestOffList.length && workRestOffList.includes(date)) {
                    return "is-workRestOff";
                }

                return "is-weekend";
            }

            // 休息日标红
            if (weekendList.length && weekendList.includes(date)) {
                return "is-weekend";
            }

            // 既非工作日也非休息日
            if (workRestOffList.length && workRestOffList.includes(date)) {
                return "is-workRestOff";
            }
        },

        lunarDate(pDate, item) {
            const date = new Date(item.date);
            const curYear = date.getFullYear(); // 当前年份
            const curMonth = date.getMonth() + 1; // 当前月份
            const curDay = date.getDate(); // 当前日期
            const lunarDate = getLunar(curYear, curMonth, curDay);
            if (lunarDate.dateStr.indexOf("初一") > -1) {
                return lunarDate.dateStr.slice(0, 2);
            } else {
                return lunarDate.dateStr.slice(2, 4);
            }
        },
        async getHoliday() {
            const res = await schedulingHttp.workcalendarGetWorkCalendar({
                year: this.year,
                month: this.month,
            });
            this.holidayList = res.data.data;
        },
        getHolidayInfo(date) {
            this.holidayList.forEach((item) => {
                if (date == item.workDate) {
                    return item;
                }
            });
        },
    },
    beforeDestroy() {
        window.removeEventListener("keydown");
        window.removeEventListener("keyup");
    },
};
</script>
  
  <style lang="less" scoped>
.calendar-header,
.calendar-week {
    user-select: none;
    .is-disabled {
        cursor: not-allowed;
        opacity: 0.5;
    }
}
.tiled-calendar {
    height: 100%;
    box-sizing: border-box;
    margin: 0 20px 10px;
    font-size: 14px;
    ul,
    li {
        margin: 0;
        padding: 0;
    }
    .calendar-header {
        border-bottom: 1px solid #edeef1;
        padding: 8px 0;
        color: #1b1f26;
        text-align: center;
        margin-bottom: 8px;
    }
    .calendar-week {
        display: flex;
        height: 28px;
        line-height: 28px;
        border-right: none;
        border-left: none;
        margin-bottom: 2px;
        .calendar-week-item {
            list-style-type: none;
            width: 14.28%;
            text-align: center;
            color: #737985;
        }
    }
    .calendar-body {
        display: flex;
        flex-wrap: wrap;
        margin-top: 5px;
        .calendar-day {
            width: 14.28%;
            text-align: center;
            height: 44px;
            line-height: 44px;
            position: relative;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            .calendar-day-item {
                display: block;
                border-radius: 50%;
                cursor: pointer;
                user-select: none;
                color: #1b1f26;
                p {
                    width: 100%;
                    line-height: 1 !important;
                    font-size: 12px;
                    margin: 2px 0;
                }
                &:hover {
                    background: rgba(69, 115, 243, 0.12);
                }
            }
            .is {
                &-today,
                &-selected {
                    border: 1px solid #e60012;
                    &:hover {
                        background: rgba(69, 115, 243, 0.12);
                    }
                }
                &-selected {
                    border: 1px solid #4573f3;
                    &:hover {
                        background: none;
                    }
                }
                &-disabled {
                    cursor: not-allowed;
                    color: #9e9e9e;
                    &:hover {
                        background: none;
                    }
                }
                &-weekend {
                    color: #e60012;
                }
                &-workRestOff {
                    color: #ff7d00;
                }
                &-disabled {
                    &.is-workRestOff {
                        color: rgba(255, 125, 0, 0.4);
                    }
                }
                &-disabled {
                    &.is-weekend {
                        color: rgba(230, 0, 18, 0.4);
                    }
                }
                &-work {
                    color: #1b1f26;
                }
                &-disabled.is-work {
                    color: #9e9e9e;
                }
            }
        }
    }
}
</style>
  